use scraper::{Html, Selector};
use serde::{Deserialize, Serialize};

use crate::REQWEST_CLIENT;
use anyhow::{anyhow, Result};
/// 基金经理
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct FundJjjl {
    pub report_date: String,     // 上任日期
    pub name: String,            // 姓名
    pub desc: String,            // 简介
    pub data: Vec<FundJjjlData>, // 历任基金一览
}

/// 基金代码	基金名称	基金类型	起始时间	截止时间	任职天数	任职回报	同类平均	同类排名
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct FundJjjlData {
    pub fund_code: String,        // 基金代码
    pub fund_name: String,        // 基金名称
    pub fund_type: String,        // 基金类型
    pub start_time: String,       // 起始时间
    pub end_time: String,         // 截止时间
    pub tenure_days: String,      // 任职天数
    pub tenure_return: String,    // 任职回报
    pub category_average: String, // 同类平均
    pub category_ranking: String, // 同类排名
}

impl FundJjjl {
    /// 基金经理 Referer: https://fundf10.eastmoney.com/jjjl_159001.html
    ///
    pub async fn fund_jjjl(code: &str) -> Result<Vec<FundJjjl>> {
        // GET /jjjl_159001.html HTTP/1.1
        // Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
        // Accept-Encoding: gzip, deflate, br
        // Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
        // Cache-Control: no-cache
        // Connection: keep-alive
        // Cookie: qgqp_b_id=d6299473145338f68687834ba37fa719; st_si=77687174285423; ASP.NET_SessionId=5ufgex2sjbo4p44lwytenq3s; searchbar_code=159834; AUTH_FUND.EASTMONEY.COM_GSJZ=AUTH*TTJJ*TOKEN; EMFUND0=01-29%2015%3A02%3A07@%23%24%u534E%u590F%u4E2D%u8BC1%u5168%u6307%u623F%u5730%u4EA7ETF@%23%24515060; EMFUND1=01-30%2014%3A41%3A22@%23%24%u534E%u6CF0%u67CF%u745E%u6D88%u8D39%u6210%u957F%u6DF7%u5408@%23%24001069; EMFUND2=01-30%2014%3A45%3A59@%23%24%u5E7F%u53D1%u6052%u751F%u6D88%u8D39%28QDII-ETF%29@%23%24159699; EMFUND3=01-30%2014%3A47%3A24@%23%24%u5357%u65B9%u7EA2%u5229%u4F4E%u6CE250ETF@%23%24515450; EMFUND4=01-31%2015%3A21%3A23@%23%24%u56FD%u8054%u4E2D%u8BC1%u7164%u70AD%u6307%u6570%28LOF%29A@%23%24168204; EMFUND5=02-02%2008%3A34%3A56@%23%24%u666F%u987A%u957F%u57CE%u652F%u67F1%u4EA7%u4E1A%u6DF7%u5408@%23%24260117; EMFUND6=02-02%2010%3A30%3A22@%23%24%u897F%u90E8%u5229%u5F97%u805A%u79BE%u6DF7%u5408A@%23%24007423; EMFUND7=02-26%2016%3A07%3A01@%23%24%u91D1%u9E70%u6DFB%u76C8%u7EAF%u503A%u503A%u5238A@%23%24003384; EMFUND8=02-27%2010%3A51%3A37@%23%24%u534E%u590F%u6210%u957F%u6DF7%u5408@%23%24000001; EMFUND9=02-27 13:53:07@#$%u534E%u6CF0%u67CF%u745E%u5357%u65B9%u4E1C%u82F1%u6052%u751F%u79D1%u6280%28QDII-ETF%29@%23%24513130; st_asi=delete; HAList=ty-1-600055-%u4E07%u4E1C%u533B%u7597%2Cty-0-000001-%u5E73%u5B89%u94F6%u884C%2Cty-0-159001-%u8D27%u5E01ETF%2Cty-0-161127-%u6807%u666E%u751F%u7269%u79D1%u6280LOF%2Cty-1-513130-%u6052%u751F%u79D1%u6280ETF%2Cty-0-300078-%u601D%u521B%u533B%u60E0%2Cty-0-300486-%u4E1C%u6770%u667A%u80FD%2Cty-1-513360-%u6559%u80B2ETF%2Cty-0-300478-%u676D%u5DDE%u9AD8%u65B0%2Cty-0-301589-N%u8BFA%u74E6; st_pvi=47260449691882; st_sp=2024-01-12%2017%3A28%3A27; st_inirUrl=https%3A%2F%2Fwww.google.com.hk%2F; st_sn=1199; st_psi=20240305101359771-112200305283-7063050807
        // Host: fundf10.eastmoney.com
        // Pragma: no-cache
        // Sec-Fetch-Dest: document
        // Sec-Fetch-Mode: navigate
        // Sec-Fetch-Site: none
        // Sec-Fetch-User: ?1
        // Upgrade-Insecure-Requests: 1
        // User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36
        // sec-ch-ua: "Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"
        // sec-ch-ua-mobile: ?0
        // sec-ch-ua-platform: "macOS"

        let request_url = format!("https://fundf10.eastmoney.com/jjjl_{code}.html");
        let response = REQWEST_CLIENT.get(request_url)
        .header(reqwest::header::ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7")
        .header(reqwest::header::ACCEPT_ENCODING, "gzip, deflate, br")
        .header(reqwest::header::ACCEPT_LANGUAGE, "zh-CN,zh;q=0.9,en;q=0.8")
        .header(reqwest::header::CACHE_CONTROL,"no-cache")
        .header(reqwest::header::CONNECTION,"keep-alive")
        // .header(reqwest::header::COOKIE, "qgqp_b_id=d6299473145338f68687834ba37fa719; st_si=77687174285423; AUTH_FUND.EASTMONEY.COM_GSJZ=AUTH*TTJJ*TOKEN; EMFUND0=01-16%2016%3A57%3A06@%23%24%u4E2D%u822A%u65B0%u8D77%u822A%u7075%u6D3B%u914D%u7F6E%u6DF7%u5408A@%23%24005537; EMFUND1=01-16%2017%3A04%3A53@%23%24%u91D1%u4FE1%u6D88%u8D39%u5347%u7EA7%u80A1%u7968A@%23%24006692; EMFUND2=01-16%2020%3A01%3A56@%23%24%u5357%u65B9%u4E0A%u8BC1380ETF@%23%24510290; EMFUND3=01-29%2015%3A02%3A07@%23%24%u534E%u590F%u4E2D%u8BC1%u5168%u6307%u623F%u5730%u4EA7ETF@%23%24515060; EMFUND4=01-30%2014%3A41%3A22@%23%24%u534E%u6CF0%u67CF%u745E%u6D88%u8D39%u6210%u957F%u6DF7%u5408@%23%24001069; EMFUND5=01-30%2014%3A45%3A59@%23%24%u5E7F%u53D1%u6052%u751F%u6D88%u8D39%28QDII-ETF%29@%23%24159699; EMFUND6=01-30%2014%3A47%3A24@%23%24%u5357%u65B9%u7EA2%u5229%u4F4E%u6CE250ETF@%23%24515450; EMFUND7=01-31%2015%3A21%3A23@%23%24%u56FD%u8054%u4E2D%u8BC1%u7164%u70AD%u6307%u6570%28LOF%29A@%23%24168204; EMFUND8=02-02%2008%3A34%3A56@%23%24%u666F%u987A%u957F%u57CE%u652F%u67F1%u4EA7%u4E1A%u6DF7%u5408@%23%24260117; EMFUND9=02-02 10:30:22@#$%u897F%u90E8%u5229%u5F97%u805A%u79BE%u6DF7%u5408A@%23%24007423; st_asi=delete; HAList=ty-1-513130-%u6052%u751F%u79D1%u6280ETF%2Cty-0-300078-%u601D%u521B%u533B%u60E0%2Cty-0-300486-%u4E1C%u6770%u667A%u80FD%2Cty-1-513360-%u6559%u80B2ETF%2Cty-0-300478-%u676D%u5DDE%u9AD8%u65B0%2Cty-0-301589-N%u8BFA%u74E6%2Cty-1-603135-%u4E2D%u91CD%u79D1%u6280%2Cty-0-000001-%u5E73%u5B89%u94F6%u884C%2Cty-0-002400-%u7701%u5E7F%u96C6%u56E2%2Cty-1-601127-%u8D5B%u529B%u65AF; st_pvi=47260449691882; st_sp=2024-01-12%2017%3A28%3A27; st_inirUrl=https%3A%2F%2Fwww.google.com.hk%2F; st_sn=438; st_psi=20240226102321941-113200301321-9024721593")
        .header(reqwest::header::HOST,"fundf10.eastmoney.com")
        .header(reqwest::header::PRAGMA, "no-cache")
        // .header(reqwest::header::REFERER , "https://fundf10.eastmoney.com/ccmx_000001.html")
        .header(reqwest::header::USER_AGENT, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36")
        .header("Sec-Ch-Ua", "\"Not A(Brand\";v=\"99\", \"Google Chrome\";v=\"121\", \"Chromium\";v=\"121\"")
        .header("Sec-Ch-Ua-Mobile", "?0")
        .header("Sec-Ch-Ua-Platform", "\"macOS\"")
        .header("Sec-Fetch-Dest", "empty")
        .header("Sec-Fetch-Mode", "cors")
        .header("Sec-Fetch-Site", "same-origin")
        .send()
        .await?;

        let body = response.text().await?;
        println!("*** body={}\n\n", body);

        Self::extract_data(&body)
    }

    fn extract_data(html: &str) -> Result<Vec<FundJjjl>> {
        let mut fund_jjjls = Vec::new();
        let document = Html::parse_document(html);
        // <div class="jl_intro">
        let jl_intro_selector = Selector::parse("div.jl_intro").map_err(|e| anyhow!("{}", e))?;
        for (_index, div_box) in document.select(&jl_intro_selector).enumerate() {
            println!("\n\n jl_intro= {}", &div_box.html());

            let box_data = Self::extract_jl_intro(&div_box.html())?;
            fund_jjjls.push(box_data);
        }

        // <div class="jl_office">
        let jl_office_selector = Selector::parse("div.jl_office").map_err(|e| anyhow!("{}", e))?;
        for (index, div_box) in document.select(&jl_office_selector).enumerate() {
            println!("\n\n jl_office= {}", &div_box.html());

            let box_data = Self::extract_jl_history(&div_box.html())?;

            fund_jjjls.get_mut(index).unwrap().data = box_data;
        }

        Ok(fund_jjjls)
    }

    // 基金经理简介
    fn extract_jl_intro(html: &str) -> Result<FundJjjl> {
        let mut fund_jjjl = FundJjjl {
            data: Vec::new(),
            ..Default::default()
        };
        let document = Html::parse_document(html);
        let name_selector = Selector::parse("div.text p a").map_err(|e| anyhow!("{}", e))?;
        if let Some(element) = document.select(&name_selector).next() {
            fund_jjjl.name = element.text().collect::<String>().replace("&nbsp;", "");
        }

        let div_text_p_selector = Selector::parse("div.text p").map_err(|e| anyhow!("{}", e))?;
        for (idx, p) in document.select(&div_text_p_selector).enumerate() {
            if idx == 1 {
                fund_jjjl.report_date = p.text().collect::<String>().replace("&nbsp;", "");
            } else if idx == 2 {
                fund_jjjl.desc = p.text().collect::<String>().replace("&nbsp;", "");
            }
        }

        Ok(fund_jjjl)
    }

    // 基金经理 历任基金一览
    fn extract_jl_history(html: &str) -> Result<Vec<FundJjjlData>> {
        let mut fund_jjjl_datas = Vec::new();
        let document = Html::parse_document(html);

        // <table class="w782 comm jloff">
        let table_selector =
            Selector::parse("table.w782.comm.jloff tbody tr").map_err(|e| anyhow!("{}", e))?;
        let td_selector = &Selector::parse("td").map_err(|e| anyhow!("{}", e))?;
        // <tr><th class="first" style="min-width: 60px;">基金代码</th><th>基金名称</th><th>基金类型</th><th>起始时间</th><th>截止时间</th><th>任职天数</th><th "last"="">任职回报<img class="jjjlhbTip" src="https://j5.dfcfw.com/image/201307/20130708102440.gif" data-placement="bottom" style="position: relative;top: 4px;left: 2px;" title="" data-original-title="因基金成立不满六个月暂不展示业绩，详见产品详情页。"></th><th>同类平均</th><th class="tor last">同类排名<img class="jjjlhbTip" src="https://j5.dfcfw.com/image/201307/20130708102440.gif" data-placement="bottom" style="position: relative;top: 4px;left: 2px;" title="" data-original-title="因基金成立不满六个月暂不展示业绩，详见产品详情页。"></th></tr>
        // <tr><td><a href="//fund.eastmoney.com/019579.html">019579</a></td><td class="tol" style="width:160px"><a href="//fund.eastmoney.com/019579.html">易方达安汇120天持有债券A</a></td><td>债券型-长债</td><td>2023-10-31</td><td>至今</td><td>126天</td><td class="tor ">--</td><td class="tor red ">1.32%</td><td class="tor">-|4171</td></tr>
        for (_index, row) in document.select(&table_selector).enumerate() {
            let mut e_data = FundJjjlData {
                ..Default::default()
            };

            e_data.fund_code = row
                .select(td_selector)
                .nth(0)
                .map(|e| e.text().collect::<String>())
                .unwrap_or_default(); // 基金代码
            e_data.fund_name = row
                .select(td_selector)
                .nth(1)
                .map(|e| e.text().collect::<String>())
                .unwrap_or_default(); // 基金名称
            e_data.fund_type = row
                .select(td_selector)
                .nth(2)
                .map(|e| e.text().collect::<String>())
                .unwrap_or_default(); // 基金类型
            e_data.start_time = row
                .select(td_selector)
                .nth(3)
                .map(|e| e.text().collect::<String>())
                .unwrap_or_default(); // 起始时间
            e_data.end_time = row
                .select(td_selector)
                .nth(4)
                .map(|e| e.text().collect::<String>())
                .unwrap_or_default(); // 截止时间
            e_data.tenure_days = row
                .select(td_selector)
                .nth(5)
                .map(|e| e.text().collect::<String>())
                .unwrap_or_default(); // 任职天数
            e_data.tenure_return = row
                .select(td_selector)
                .nth(6)
                .map(|e| e.text().collect::<String>())
                .unwrap_or_default(); // 任职回报
            e_data.category_average = row
                .select(td_selector)
                .nth(7)
                .map(|e| e.text().collect::<String>())
                .unwrap_or_default(); // 同类平均
            e_data.category_ranking = row
                .select(td_selector)
                .nth(8)
                .map(|e| e.text().collect::<String>())
                .unwrap_or_default(); // 同类排名

            fund_jjjl_datas.push(e_data);
        }

        Ok(fund_jjjl_datas)
    }
}

#[cfg(test)]
mod test {
    use crate::fund::fund_jjjl::FundJjjl;

    #[tokio::test]
    async fn test_fund_jjjl() {
        let result = FundJjjl::fund_jjjl("000001").await;

        // println!("result={:?}", result);

        assert_eq!(result.is_ok(), true);
        if let Ok(fund_jjjls) = result {
            println!("\n\nfund_jjjls= {:?}\n", fund_jjjls);
        }
    }
}
